package com.vshop.platform.system.crud.dao;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.vshop.platform.system.domain.entity.SysUser;
import com.vshop.platform.system.crud.mapper.SysUserMapper;
import com.vshop.platform.system.domain.param.SysUserParam;
import org.springframework.stereotype.Repository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

import static com.mybatisflex.core.query.QueryMethods.*;
import static com.vshop.platform.system.domain.entity.table.SysDeptTableDef.SysDeptTable;
import static com.vshop.platform.system.domain.entity.table.SysUserTableDef.SysUserTable;


/**
 * 用户信息表 服务层实现。
 *
 * @author vshop
 * @since 2024-11-18
 */
@RequiredArgsConstructor
@Slf4j
@Repository
public class SysUserDao extends ServiceImpl<SysUserMapper, SysUser> {

    public QueryWrapper buildQueryWrapper(SysUserParam param) {
        /*select u.user_id, u.tenant_id, u.dept_id, u.nick_name, u.user_name, u.user_type, u.email, u.avatar, u.phone_number, u.gender, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader
        from sys_user u
        left join sys_dept d on u.dept_id = d.dept_id
        where u.del_flag = '0'*/
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(SysUserTable.UserId, SysUserTable.TenantId, SysUserTable.DeptId, SysUserTable.NickName,
                        SysUserTable.UserName, SysUserTable.UserType, SysUserTable.Email, SysUserTable.Avatar,
                        SysUserTable.PhoneNumber, SysUserTable.Sex, SysUserTable.Status, SysUserTable.DeleteFlag,
                        SysUserTable.LoginIp, SysUserTable.LoginDate, SysUserTable.CreateBy,
                        SysUserTable.CreateTime, SysUserTable.Remark, SysDeptTable.DeptName, SysDeptTable.Leader)
                .from(SysUserTable.as("u"))
                .leftJoin(SysDeptTable).as("d").on(SysDeptTable.DeptId.eq(SysUserTable.DeptId));
        if (ObjectUtil.isNotNull(param.getUserId())) {
            queryWrapper.and(SysUserTable.UserId.eq(param.getUserId()));
        }
        if (StrUtil.isNotEmpty(param.getUserName())) {
            queryWrapper.and(SysUserTable.UserName.like(param.getUserName()));
        }
        if (StrUtil.isNotEmpty(param.getStatus())) {
            queryWrapper.and(SysUserTable.Status.eq(param.getStatus()));
        }
        if (StrUtil.isNotEmpty(param.getPhoneNumber())) {
            queryWrapper.and(SysUserTable.PhoneNumber.like(param.getPhoneNumber()));
        }
        Map<String, Object> params = param.getParams();
        if (params.get("beginTime") != null && params.get("endTime") != null) {
            queryWrapper.and(SysUserTable.CreateTime.between(params.get("beginTime"),
                    params.get("endTime")));
        }
        if (ObjectUtil.isNotNull(param.getDeptId())) {
            queryWrapper.and(SysUserTable.DeptId.eq(param.getDeptId())
                    .or(SysUserTable.DeptId.in(
                            select(SysDeptTable.DeptId)
                                    .from(SysDeptTable.as("t"))
                                    .where(findInSet(number(param.getDeptId()), SysDeptTable.Ancestors)
                                            .gt(0)))
                    )
            );
        }
        queryWrapper.orderBy(SysUserTable.UserId.desc());
        return queryWrapper;
    }

    public boolean changeStatus(Long id, String status) {
        return this.updateChain()
                .from(SysUserTable)
                .set(SysUserTable.Status, status)
                .where(SysUserTable.UserId.eq(id))
                .update();
    }

    public SysUser getUserInfo(String username) {
        return this.queryChain()
                .where(SysUserTable.UserName.eq(username))
                .oneAs(SysUser.class);
    }

    public SysUser getUserInfo(Long userId, String tenantId) {
        return this.queryChain()
                .where(SysUserTable.UserId.eq(userId))
                .and(SysUserTable.TenantId.eq(tenantId))
                .oneAs(SysUser.class);
    }

    /**
     * 校验用户名称是否唯一
     *
     * @param param 用户信息
     * @return 结果
     */
    public boolean checkExistUserName(SysUserParam param) {
//        long userId = ObjectUtil.isNull(param.getUserId()) ? -1L : param.getUserId();
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(SysUserTable.UserName)
                .from(SysUserTable)
                .and(SysUserTable.UserName.eq(param.getUserName()))
                .and(SysUserTable.UserId.ne(param.getUserId()));
        return this.exists(queryWrapper);
    }

    /**
     * 校验手机号码是否唯一
     *
     * @param param 用户信息
     */
    public boolean checkExistPhone(SysUserParam param) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(SysUserTable.PhoneNumber)
                .from(SysUserTable)
                .and(SysUserTable.PhoneNumber.eq(param.getPhoneNumber()))
                .and(SysUserTable.UserId.ne(param.getUserId()));
        return this.exists(queryWrapper);
    }

    /**
     * 校验email是否唯一
     *
     * @param param 用户信息
     * @return true或者false
     */
    public boolean checkExistEmail(SysUserParam param) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(SysUserTable.Email)
                .from(SysUserTable)
                .and(SysUserTable.Email.eq(param.getEmail()))
                .and(SysUserTable.UserId.ne(param.getUserId()));
        return this.exists(queryWrapper);
    }
}
